/**CopyRight[1990-2012]<lyc2877@gmail.com>
 */
#include "./include/ProcessManager.h"

CProcessManager* CProcessManager::m_pInstance = NULL;

CProcessManager* CProcessManager::GetInstance() {
  if (NULL == m_pInstance) {
    m_pInstance = new CProcessManager();
  }
  return m_pInstance;
}

CProcessManager::CProcessManager() {
  m_pMQueue = new CMQueue(MQKEY_PROCESS);
  m_pworker = new CWorker(MQKEY_WORKER);
  m_psender = new CSender(MQKEY_SENDER);
  m_nLockFd = 0;
}

CProcessManager::~CProcessManager() {
#if 1
  if (NULL != m_pMQueue) {
    delete m_pMQueue;
  }   
  if (NULL != m_pworker) {
    delete m_pworker;
  }
  if (NULL != m_psender) {
    delete m_psender;
  }
#endif
#if 0
  if (NULL != CProcessManager::m_pInstance) {
    delete CProcessManager::m_pInstance;
  }   
#endif
}

void CProcessManager::process_logic(int argc, char** argv) {
  int nResult = 0;
  pid_t pid = 0;
  nResult = getopt(argc, argv, "su");
  switch (nResult) {
    case 's':
      if(true != lock(LOCK_NOWAIT)) {
        printf("Process already running!\n");
        return;
      }
      pid = fork();
      if (pid > 0) {
        return;
      }
      signal(SIGTTOU, SIG_IGN);
      signal(SIGTTIN, SIG_IGN);
      signal(SIGTSTP, SIG_IGN);
      signal(SIGHUP, SIG_IGN);
      break;
    case 'u':
      if (true == lock(LOCK_NOWAIT))
      {
        lock(UNLOCK);
        printf("No process!\n");
      } else {
        printf("Find process! stopping...\n");
        stop();
      }
      return;
      break;
    case '?':
    default:
      printf("error!\n");
      return;
      break;
  }
  boot();
  return;
}
void CProcessManager::boot() {
  TMsg t_msg;
  this->create_thread(m_pworker);
  this->create_thread(m_pworker);
  this->create_thread(m_pworker);
  this->create_thread(m_pworker);
  this->create_thread(m_pworker);
  this->create_thread(m_pworker);
  this->create_thread(m_pworker);
  this->create_thread(m_pworker);
  this->create_thread(m_pworker);
  this->create_thread(m_pworker);
  this->create_thread(m_pworker);
  sleep(3);
  this->create_thread(m_psender);

  while (1) {
    m_pMQueue->recv_msg(&t_msg);
    if (STOP == t_msg.m_ucState) {
      printf("Get exit singal!\n");
      lock(UNLOCK);
      break;
    }
  }
  system("ipcrm -Q 10000");
  return;
}
void CProcessManager::stop() {
  TMsg t_msg;
  t_msg.m_ucState = STOP;
  t_msg.m_lTo = MQKEY_PROCESS;
  m_pMQueue->send_msg(&t_msg);
  printf("Exit signal sended!\n");
  return;
}

bool CProcessManager::lock(int in_nMode) {

  char szPid[32] = {0};
  snprintf(szPid, 32, "%ld", (long)getpid());
  if (0 == m_nLockFd) {
    m_nLockFd = open(LOCK_FILE, O_RDWR|O_CREAT, 0640);
  }
  if (m_nLockFd < 0) {
    //printf("open file error!\n");
    return false;
  }
  if (0 != flock(m_nLockFd, in_nMode)) {
    //printf("lock file error!\n");
    return false;
  }
  if (UNLOCK == in_nMode) {
    close(m_nLockFd);
  }
  else {
    ftruncate(m_nLockFd, 0);
    write(m_nLockFd, szPid, strlen(szPid));
    //printf("Lock success![%d]\n", m_nLockFd);
  }
  return true;
}

int32_t CProcessManager::create_thread(CThread* in_pt) {
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr,
                              PTHREAD_CREATE_DETACHED);

  pthread_t tt;
  pthread_create(&tt, &attr, thread, in_pt);
  pthread_detach(tt);
  printf("[%ld] start success\n", tt);
  return 0;
}

void* thread(void* in_pv) {
  CThread *p_th = (CThread*)in_pv;
  p_th->start_thread();
  p_th->stop_thread();
  return NULL;
}
